/* 	SymTable.java
	From: Department of CSE
	Authors: Le Minh Vu, Nguyen Hua Phung
	Date: 15/11/2007
*/
package MP.staticchecker;

import java.util.Stack;
import MP.CompilationException;
import MP.lexicalanalysis.*;
import MP.MPC;
abstract public class SymTable {

	final Stack<SymEntry> tab = new Stack<SymEntry>();
	final Stack<Integer>  scope = new Stack<Integer>();
	//final Stack<String> functionScope = new Stack<String>();
	public void init() {
		SymEntry readInt =new SymEntry(new Token(Token.ID,"readInt"),new FunctionType(null,Type.INTTYPE));
		readInt.setObject(MPC.LIBNAME);
		insertId(readInt);
		SymEntry readReal =new SymEntry(new Token(Token.ID,"readBool"),new FunctionType(null,Type.REALTYPE));
		readReal.setObject(MPC.LIBNAME);
		insertId(readReal);
		SymEntry readBool =new SymEntry(new Token(Token.ID,"readBool"),new FunctionType(null,Type.BOOLTYPE));
		readBool.setObject(MPC.LIBNAME);
		insertId(readBool);
		SymEntry writeLn = new SymEntry(new Token(Token.ID,"writeLn"),new FunctionType(null,Type.VOIDTYPE));
		writeLn.setObject(MPC.LIBNAME);
		insertId(writeLn);
		SymEntry writeInt = new SymEntry(new Token(Token.ID,"writeInt"),new FunctionType(new ProductType(Type.INTTYPE,null),Type.VOIDTYPE));
		writeInt.setObject(MPC.LIBNAME);
		insertId(writeInt);
		SymEntry writeIntLn = new SymEntry(new Token(Token.ID,"writeIntLn"),new FunctionType(new ProductType(Type.INTTYPE,null),Type.VOIDTYPE));
		writeIntLn.setObject(MPC.LIBNAME);
		insertId(writeIntLn);
		SymEntry writeReal = new SymEntry(new Token(Token.ID,"writeReal"),new FunctionType(new ProductType(Type.REALTYPE,null),Type.VOIDTYPE));
		writeReal.setObject(MPC.LIBNAME);
		insertId(writeReal);
		SymEntry writeRealLn = new SymEntry(new Token(Token.ID,"writeRealLn"),new FunctionType(new ProductType(Type.REALTYPE,null),Type.VOIDTYPE));
		writeRealLn.setObject(MPC.LIBNAME);
		insertId(writeRealLn);
		SymEntry writeBool = new SymEntry(new Token(Token.ID,"writeBool"),new FunctionType(new ProductType(Type.BOOLTYPE,null),Type.VOIDTYPE));
		writeBool.setObject(MPC.LIBNAME);
		insertId(writeBool);
		SymEntry writeBoolLn = new SymEntry(new Token(Token.ID,"writeBoolLn"),new FunctionType(new ProductType(Type.BOOLTYPE,null),Type.VOIDTYPE));
		writeBoolLn.setObject(MPC.LIBNAME);
		insertId(writeBoolLn);
		SymEntry writeStr = new SymEntry(new Token(Token.ID,"writeStr"),new FunctionType(new ProductType(Type.STRINGTYPE,null),Type.VOIDTYPE));
		writeStr.setObject(MPC.LIBNAME);
		insertId(writeStr);
		SymEntry writeStrLn = new SymEntry(new Token(Token.ID,"writeStrLn"),new FunctionType(new ProductType(Type.STRINGTYPE,null),Type.VOIDTYPE));
		writeStrLn.setObject(MPC.LIBNAME);
		insertId(writeStrLn);
	}
	// invoked when entering a new scope
	abstract public void enterScope();
	//// invoked when exitting a scope
	abstract public void exitScope() throws CompilationException ;
	// return (1) Integer representing the position of sym in the table if sym.id.Lexeme has not been declared in the current scope
	//	      (2) SymEntry of another sym' whose id.Lexeme is the same as sym.id.Lexeme
	abstract public Object insertId(SymEntry sym);
	// return (1) SymEntry whose lexeme is lexeme
	//             (2) null if there is no entry whose lexeme is lexeme
	abstract public SymEntry lookup(String lexeme);
	// return (1) integer representing the scope of an id whose lexeme is lexeme. 
	//	      (2) -1 if there is no id whose lexeme is lexeme
	abstract public int getScope(String lexeme);


}

class IllegalOperationException extends CompilationException {

      public String getMessage() {
        return "Illegal Symbol Table Operation";
      }
}

